package com.loong.web.gp4j.service.attach;

import java.io.File;
import java.io.IOException;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.loong.tool.lang.Images;
import com.loong.tool.lang.Streams;
import com.loong.tool.lang.Strings;
import com.loong.tool.secret.security.digest.Digest;
import com.loong.web.gp4j.bean.param.attach.AttachCs;
import com.loong.web.gp4j.bean.param.attach.AttachParam;
import com.loong.web.gp4j.bean.schema.attach.AttachSchema;
import com.loong.web.gp4j.bean.vo.util.CodeVo;
import com.loong.web.gp4j.dao.attach.AttachCache;
import com.loong.web.gp4j.dao.attach.AttachDao;
import com.loong.web.gp4j.service.error.ErrorService;
import com.loong.web.suppert.collection.vo.ResultVo;
import com.loong.web.suppert.collection.vo.ResultVoFactory;

/**
 * 附件服务
 *
 * @author 张成轩
 */
@Service
public class AttachService {

	@Resource
	private ErrorService errorService;

	@Value("${attach.path}")
	private String serverPath;
	@Value("${upload.compress.md}")
	private Integer md;
	@Value("${upload.compress.xs}")
	private Integer xs;
	@Resource
	private AttachDao attachDao;
	@Resource
	private AttachCache attachCache;

	/**
	 * 附件上传
	 * 
	 * @param file 文件对象
	 * @param c 是否压缩
	 * @return 返回对象
	 */
	public ResultVo<?> upload(MultipartFile file, Boolean c) {

		String name;
		try {
			name = Digest.digest(file.getInputStream());
		} catch (IOException e) {
			errorService.error(e);
			return ResultVoFactory.fail("文件解析失败");
		}

		// 判断文件是否存在
		AttachSchema attach = attachDao.getBySign(name);
		if (attach == null) {
			// 保存文件
			String path = Strings.join("/", name.substring(0, 2), name.substring(0, 4), name);
			File f = new File(serverPath, path);
			try {
				Streams.write(file.getInputStream(), f);
			} catch (IOException e) {
				errorService.error(e);
				return ResultVoFactory.fail("保存文件失败");
			}
			// 保存压缩图
			String mdPath = null;
			String smPath = null;
			if (c != null && c) {
				mdPath = path + "_md";
				File cf = new File(serverPath, mdPath);
				try {
					Images.resize(f, md, cf);
				} catch (IOException | RuntimeException e) {
					errorService.error(e);
					f.delete();
					return ResultVoFactory.fail("压缩图片失败");
				}
				smPath = path + "_sm";
				File ccf = new File(serverPath, smPath);
				try {
					Images.resize(cf, xs, ccf);
				} catch (IOException | RuntimeException e) {
					errorService.error(e);
					f.delete();
					cf.delete();
					return ResultVoFactory.fail("二级压缩图片失败");
				}
			}
			// 插入数据
			attach = new AttachSchema();
			AttachAdapter.convert(name, path, mdPath, smPath, attach);
			attachDao.insert(attach);
		}

		// 封装返回对象
		CodeVo vo = new CodeVo();
		AttachAdapter.convert(attach, vo);
		return ResultVoFactory.succ(vo);
	}

	/**
	 * 获取附件
	 * 
	 * @param response 响应
	 * @param param 参数
	 */
	public void get(HttpServletResponse response, AttachParam param) {

		// 查询缓存
		AttachSchema attach = attachCache.get(param.getSign());
		if (attach == null) {
			// 查询数据
			attach = attachDao.getBySign(param.getSign());
			if (attach == null)
				return;
			// 加入缓存
			attachCache.put(param.getSign(), attach);
		}
		File file = null;
		// 判断附件类型
		if (AttachCs.MD.equals(param.getC()) && Strings.isNotNull(attach.getMd()))
			file = new File(serverPath, attach.getMd());
		else if (AttachCs.SM.equals(param.getC()) && Strings.isNotNull(attach.getSm()))
			file = new File(serverPath, attach.getSm());
		else
			file = new File(serverPath, attach.getOriginal());
		try {
			// 读取流
			Streams.read(response.getOutputStream(), file);
		} catch (IOException e) {
			errorService.error(e);
		}
	}
}
